/*
 * SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
 *
 * SPDX-License-Identifier: MulanPSL-2.0
 */
#![allow(
    dead_code,
    mutable_transmutes,
    non_camel_case_types,
    non_snake_case,
    non_upper_case_globals,
    unused_assignments,
    unused_mut
)]

use crate::common::*;

extern "C" {
    fn malloc(_: libc::c_ulong) -> *mut libc::c_void;
    fn free(_: *mut libc::c_void);
    fn __errno_location() -> *mut libc::c_int;
    fn fcntl(__fd: libc::c_int, __cmd: libc::c_int, _: ...) -> libc::c_int;
    fn strlen(_: *const libc::c_char) -> libc::c_ulong;
    fn audit_open() -> libc::c_int;
    fn audit_log_user_command(
        audit_fd: libc::c_int,
        type_0: libc::c_int,
        command: *const libc::c_char,
        tty: *const libc::c_char,
        result: libc::c_int,
    ) -> libc::c_int;
    fn sudo_strlcpy(dst: *mut libc::c_char, src: *const libc::c_char, siz: size_t) -> size_t;
    fn sudo_warn_nodebug_v1(fmt: *const libc::c_char, _: ...);
    fn sudo_warnx_nodebug_v1(fmt: *const libc::c_char, _: ...);
    fn sudo_debug_printf2_v1(
        func: *const libc::c_char,
        file: *const libc::c_char,
        line: libc::c_int,
        level: libc::c_int,
        fmt: *const libc::c_char,
        _: ...
    );
    static mut sudoers_subsystem_ids: [libc::c_uint; 0];
}

/*
 * Open audit connection if possible.
 * Returns audit fd on success and -1 on failure.
 */
fn linux_audit_open() -> libc::c_int {
    static mut au_fd: libc::c_int = -(1 as libc::c_int);

    unsafe {
        debug_decl!(SUDOERS_DEBUG_AUDIT!());

        if au_fd != -(1 as libc::c_int) {
            debug_return_int!(au_fd);
        }
        au_fd = audit_open();
        if au_fd == -(1 as libc::c_int) {
            /* Kernel may not have audit support. */
            if *__errno_location() == EINVAL
                || *__errno_location() == EPROTONOSUPPORT
                || *__errno_location() == EAFNOSUPPORT
            {
                au_fd = AUDIT_NOT_CONFIGURED;
            } else {
                sudo_warn!(b"unable to open audit system\0" as *const u8 as *const libc::c_char,);
            }
        } else {
            fcntl(au_fd, F_SETFD, FD_CLOEXEC);
        }
        debug_return_int!(au_fd);
    } //unsafe
}
#[no_mangle]
pub fn linux_audit_command(
    mut argv: *mut *mut libc::c_char,
    mut result: libc::c_int,
) -> libc::c_int {
    let mut au_fd: libc::c_int = 0;
    let mut rc: libc::c_int = -(1 as libc::c_int);
    let mut command: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut cp: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut av: *mut *mut libc::c_char = std::ptr::null_mut::<*mut libc::c_char>();
    let mut size: size_t = 0;
    let mut n: size_t = 0;

    unsafe {
        debug_decl!(SUDOERS_DEBUG_AUDIT!());

        /* Don't return an error if auditing is not configured. */
        au_fd = linux_audit_open();
        if au_fd < 0 {
            debug_return_int!(if au_fd == AUDIT_NOT_CONFIGURED { 0 } else { -1 });
        }
        /* Convert argv to a flat string. */
        size = 0 as libc::c_int as size_t;
        av = argv;
        while !(*av).is_null() {
            size = (size as libc::c_ulong)
                .wrapping_add((strlen(*av)).wrapping_add(1 as libc::c_int as libc::c_ulong))
                as size_t as size_t;
            av = av.offset(1);
        }
        command = malloc(size) as *mut libc::c_char;
        if command.is_null() {
            sudo_warnx!(
                b"%s: %s\0" as *const u8 as *const libc::c_char,
                get_function_name!(),
                b"unable to allocate memory\0" as *const u8 as *const libc::c_char
            );
            // goto done;
            free(command as *mut libc::c_void);
            debug_return_int!(rc);
        }

        av = argv;
        cp = command;
        loop {
            if (*av).is_null() {
                break;
            }
            n = sudo_strlcpy(
                cp,
                *av,
                size.wrapping_sub(cp.offset_from(command) as libc::c_long as libc::c_ulong),
            );
            if n >= size.wrapping_sub(cp.offset_from(command) as libc::c_long as libc::c_ulong) {
                sudo_warnx!(
                    b"internal error, %s overflow\0" as *const u8 as *const libc::c_char,
                    get_function_name!()
                );
                // goto done;
                free(command as *mut libc::c_void);
                debug_return_int!(rc);
            }
            cp = cp.offset(n as isize);
            let fresh0 = cp;
            cp = cp.offset(1);
            *fresh0 = ' ' as i32 as libc::c_char;
            av = av.offset(1);
        }
        cp = cp.offset(-1);
        *cp = '\0' as i32 as libc::c_char;

        /* Log command, ignoring ECONNREFUSED on error. */

        if audit_log_user_command(
            au_fd,
            AUDIT_USER_CMD,
            command,
            std::ptr::null::<libc::c_char>(),
            result,
        ) <= 0 as libc::c_int
            && *__errno_location() != ECONNREFUSED
        {
            sudo_warn!(b"unable to send audit message\0" as *const u8 as *const libc::c_char,);
            // goto done;
            free(command as *mut libc::c_void);
            debug_return_int!(rc);
        }

        /*if audit_log_user_command(
            au_fd,
            AUDIT_USER_CMD,
            command,
            std::ptr::null::<libc::c_char>(),
            result,
        ) <= 0 as libc::c_int
        {
            if *__errno_location() != ECONNREFUSED {
                sudo_warn!(b"unable to send audit message\0" as *const u8 as *const libc::c_char,);
                // goto done;
                free(command as *mut libc::c_void);
                debug_return_int!(rc);
            }
        }*/

        rc = 0;

        free(command as *mut libc::c_void);
        debug_return_int!(rc);
    } //unsafe
}
